home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / p < prev    next >
Encoding:
Korn shell script  |  1997-08-26  |  8.0 KB  |  270 lines

  1. #!/bin/ksh
  2. # @(#) p.ksh 1.2 97/06/26
  3. # p: page compressed & plain files in the order given 
  4. # 92/01/23 john h. dubois iii (john@armory.com)
  5. # 92/02/14 changed incorrect zpack to pcat
  6. # 92/02/16 added help
  7. # 92/10/11 search for file.Z and file.z if file not found
  8. # 92/10/18 pass options to pager
  9. # 93/11/09 Understand gzipped files too
  10. #          Wait after printing message about unreadable files
  11. #          Make less prompt include name of file being uncompressed
  12. # 95/08/05 Added -<num> option
  13. # 96/10/27 Make -s required for strings option.  Added m option.
  14. # 96/12/16 Made options be passed correctly to pager again.
  15. # 96/12/19 Use LESSOPEN if pager is less
  16. # 97/06/26 Added v option.
  17.  
  18. # Usage: PageInput exec filename pager-options
  19. # Page the standard input.  If filename is non-null and the pager is less,
  20. # the filename is put in the prompt.  exec should be either null, or the
  21. # word "exec" to cause the pager to be exec'd.  pager-options are passed to
  22. # the pager.
  23. function PageInput {
  24.     typeset exec=$1 filename=$2 Opts=$3
  25.  
  26.     # If pager is less, set the prompt to include the name of
  27.     # the file being uncompressed.  Escape dots in the extension
  28.     # because less treats . specially in prompts.
  29.     if [[ "$PAGER" = *less && -n "$filename" ]]; then
  30.     fsub . "\." "$filename"
  31.     $exec $PAGER "-P[$fsub_ret] (%pb\\%)" $Opts
  32.     else
  33.     $exec $PAGER $Opts
  34.     fi
  35. }
  36.  
  37. # Usage: Page filename pager-options input-file ...
  38. # No input-file indicates that the standard input should be paged.
  39. # filename is used to pass a filename (if there is one available) that the
  40. # standard input is coming from, so that it can be put in a prompt for less.
  41. # If the global stringsCmd is not null, each input file is run through it.
  42. # If the global "exec" is set to exec, the pager is exec'ed.  If stringsCmd
  43. # is set, it is exec'ed for the last file.
  44. function Page {
  45.     typeset filename=$1 Opts=$2 file
  46.  
  47.     shift 2
  48.  
  49.     if [ $# -eq 0 ]; then    # Page input
  50.     [ -n "$stringsCmd" ] && 
  51.     $stringsCmd | PageInput "$exec" "$filename" "$Opts" ||
  52.     PageInput "$exec" "$filename" "$Opts"
  53.     elif [ -n "$stringsCmd" ]; then
  54.     while [ $# -gt 1 ]; do
  55.         $stringsCmd < "$1" | PageInput "" "$1" "$Opts"
  56.         shift
  57.     done
  58.     $stringsCmd < "$1" | PageInput "$exec" "$1" "$Opts"
  59.     else
  60.     $exec $PAGER $Opts "$@"
  61.     fi
  62. }
  63.  
  64. # Usage: fsub Old New String
  65. # Replaces each instance of string Old with string New in string String
  66. # The result is put in global fsub_ret
  67. function fsub {
  68.     typeset Old=$1 New=$2 S=$3
  69.     fsub_ret=
  70.     # While the input string contains Old, peel off the part of the string
  71.     # that comes before the first instance of Old, append it and New
  72.     # to the output string, and remove the leading Old from the input string.
  73.     while [ "${S%$Old*}" != "$S" ]; do
  74.     fsub_ret="$fsub_ret${S%%$Old*}$New"
  75.     # Get rid of the leading part of the string that contains old
  76.     S=${S#*$Old}
  77. done
  78.     fsub_ret="$fsub_ret$S"    # Prepend the remaining part
  79. }
  80.  
  81. # usage: pageComp <compressor>
  82. # If compressor has changed, page any compressed files that have been stored in
  83. # comp[]
  84. # A null argument is used for uncompressed files.
  85. function pageComp {
  86.     # Page any compressed files that use any other uncompressor
  87.     if [ "$1" != "$lastComp" ] && [ ${#comp[@]} -gt 0 ]; then
  88.     [ -n "$lastComp" ] && export LESSOPEN="|exec $lastComp %s" ||
  89.     unset LESSOPEN
  90.     Page "" "$Opts" "${comp[@]}"
  91.     unset comp[*]
  92.     fi
  93.     lastComp=$1
  94. }
  95.  
  96. # Globals:
  97. # Returns match in CheckVer_ret
  98. # If version is not -1, it is taken to be a file version number.
  99. function CheckVer {
  100.     typeset file=$1
  101.  
  102.     if [ version -eq 0 ]; then
  103.     # undelete -l seems to list files in order of version, but the man
  104.     # page doesn't claim that, so use sort to make sure
  105.     undelete -l "$file" 2>/dev/null|sort -t\; -n +1 | read file || return 1
  106.     elif [ version -ne -1 ]; then
  107.     file="$file$vertail"
  108.     fi
  109.     if [ -r "$file" ]; then
  110.     CheckVer_ret=$file
  111.     return 0
  112.     fi
  113.     return 1
  114. }
  115.  
  116. ### Start of main program
  117.  
  118. DefPager=/usr/local/bin/less
  119.  
  120. alias istrue="test 0 -ne"
  121. alias isfalse="test 0 -eq"
  122. stringsCmd=
  123. exec=
  124. Debug=false
  125. typeset -i version=-1
  126.  
  127. name=${0##*/}
  128. Usage="Usage: $name [-hm] [-s<number>] [pager-option ...] [filename ...]"
  129.  
  130. # Need leading : so getopts will not complain about unknown options.
  131. while getopts :hms:v: opt; do
  132.     case $opt in
  133.     h)
  134.     print -r -- \
  135. "$name: page a file.
  136. $Usage
  137. Files are paged by the program specified in the user's PAGER
  138. environment variable, or by $DefPager if PAGER is not set.
  139. If no filename is given, text to page is read from the standard input.
  140. If filenames are given, they are either paged directly, or unpacked/
  141. uncompressed and then paged.  Files are assumed to be in packed, compressed,
  142. gzipped, hzipped, or bzipped format if the filename ends in .Z, .z, .gz, .hz,
  143. or .bz respectively.  If a filename that does not end in one of those
  144. extensions is given and is not found, it is searched for with each of those
  145. extensions attached.
  146. Each group of plain files is paged by a single instance of the pager.
  147. Each compressed file is paged by a separate instance of the pager. 
  148. Options:
  149. -h: Print this help.
  150. -m: Convert carraige returns to newlines.
  151. -s<number>: Each file is passed through \"strings -a -<number>\".  Each file is
  152.     paged individually.
  153. -v<number>: Read version <number> of each file.  This is equivalent to reading
  154.     the file named filename;<number>.  If 0 is given, the lowest-numbered
  155.     file version that exists is read.  If there is no versioned copy of the
  156.     file, an error is produced (-v0 does not extend to the 0th version).
  157. Any other initial arguments beginning with + or - are taken to be pager options
  158. and are passed to each instance of the pager.  If a pager option takes a value
  159. it should be given with the option as a single argument (with no space between
  160. the option and the value)."
  161.     exit 0
  162.     ;;
  163.     m)
  164.     [ -n "$stringsCmd" ] && stringsCmd="$stringsCmd |"
  165.     stringsCmd="$stringsCmd tr '\015' '\012'"
  166.     ;;
  167.     s)
  168.     [ -n "$stringsCmd" ] && stringsCmd="$stringsCmd |"
  169.     stringsCmd="$stringsCmd strings -a -$OPTARG"
  170.     ;;
  171.     v)
  172.     export SHOWVERSIONS=1
  173.     version=$OPTARG || exit 1
  174.     vertail=";$version"
  175.     ;;
  176.     :) 
  177.     print -r -u2 -- \
  178.     "$name: Option '$OPTARG' requires a value.  Use -h for help."
  179.     exit 1
  180.     ;;
  181.     ?)
  182.     break;    # pager option
  183.     esac
  184. done
  185.  
  186. # remove args that were options
  187. let OPTIND=OPTIND-1
  188. shift $OPTIND
  189.  
  190. # Get pager options
  191. while [[ "$1" = [-+]* ]]; do
  192.     Opts="$Opts $1"
  193.     shift
  194. done
  195.  
  196. [ -z "$PAGER" ] && PAGER=$DefPager
  197.  
  198. [[ "$PAGER" = *less ]] && useLO=true || useLO=false
  199.  
  200. # Read from stdin
  201. if [ $# = 0 ]; then
  202.     exec=exec
  203.     Page "" "$Opts"
  204. fi
  205.  
  206. typeset -i filenum=0 badfile=0
  207.  
  208. # Verify/convert filenames
  209. for file; do
  210.     if CheckVer "$file"; then
  211.     file=$CheckVer_ret
  212.     elif [[ "$file" != *.@([zZ]|[gbh]z) ]]; then
  213.     # If file does not already have a compression extension, check whether
  214.     # user specified a compressed file without giving its extension
  215.     for ext in Z z gz bz hz; do
  216.         if CheckVer "$file.$ext"; then
  217.         file=$CheckVer_ret
  218.         break
  219.         fi
  220.     done
  221.     fi
  222.     if [ ! -r "$file" ]; then
  223.     print -u2 -- "$file$vertail: cannot read."
  224.     badfile=1
  225.     else
  226.     files[filenum]=$file
  227.     let filenum+=1
  228.     fi
  229. done
  230.  
  231. if istrue badfile && [ filenum -gt 0 ]; then
  232.     print -u2 -n "Press return to continue..."
  233.     read
  234. fi
  235.  
  236. unset plain
  237.  
  238. # Page files!
  239. lastComp=
  240. for file in "${files[@]}"; do
  241.     # Get name of uncompressor
  242.     case "$file" in
  243.     *.@([zZ]|[gbh]z) ) 
  244.     # one of these is guaranteed to work, due to the pattern test above
  245.     set -- Z zcat z pcat gz gzcat bz "bzip -dc" hz "hzip -dc"
  246.     while [ $# -gt 0 ]; do
  247.         [[ "$file" = *.* && "${file##*.}" = "$1" ]] && break
  248.         shift 2
  249.     done
  250.     ;;
  251.     *)    # no compressor
  252.     set --
  253.     ;;
  254.     esac
  255.     # Page any compressed files that use any other uncompressor
  256.     pageComp "$2"
  257.     # If an uncompressed file or we're using less (and so can page multiple
  258.     # compressed files with a single instance of the pager), store filename.
  259.     # Otherwise, uncompress & page it immediately.
  260.     if $useLO || [ -z "$2" ]; then
  261.     comp[${#comp[@]}]=$file
  262.     else
  263.     $2 "$file" | Page "$file" "$Opts"
  264.     fi
  265. done
  266.  
  267. # Page any files that haven't been paged yet
  268. exec=exec
  269. pageComp "foo"    # to not match any uncompressor
  270.